/***************************************************************************
 创建者: 华磊
 开始时间: 2018.8.14
 copyright: (C) 华友高科
 修改说明: (每次有修改就添加一条，带有 修改人，修改时间，修改描述)
 example (1) hualei 2017.5.8 类的具体实现代码编写

 ***************************************************************************/
#include "messagelog.h"
#include "robotcontrol.h"
#include "domparser.h"
#include <QDebug>

MessageLog* MessageLog::messageLog = NULL;
MessageLog::MessageLog()
{
    versionInfo.componentName="MessageLog";
    versionInfo.componentVersion="V1.0";
    versionInfo.publishDate="2018.10.27";

    pthread_mutexattr_init(&msgAttr);
    pthread_mutexattr_setprotocol(&msgAttr,PTHREAD_PRIO_INHERIT);
    pthread_mutex_init(&msgThreadLock,&msgAttr);

    registerComponentVersion(versionInfo);
    saveLogFileFlag=false;

//    currentLanguage = ENUM_LAN_CHINESE;
    currentLanguage = 0;


    logName = D_TCRCONTROLLER_DATA_PATH;
    logName = logName+LOG_FILE;

    xmlLogFileName = D_TCRCONTROLLER_DATA_PATH;
    xmlLogFileName = xmlLogFileName+LOG_XML_FILE;

    m_pTranslator = new QTranslator;
    isDeviceMasterInitialOkStatus=false;

//    readLogFile();

}

bool MessageLog::isDeviceMasterInitialOk()
{
    return isDeviceMasterInitialOkStatus;
//    bool isOk=false;
//    lock();
//    for(int i = 0; i < allMsgList.size();i++)
//    {
//        if( 1900== allMsgList[i].messageCode)
//        {
//           isOk=true;
//        }
//    }
//    unlock();
//    return isOk;
}

MessageLog* MessageLog::getInstance()
{
    if(NULL == messageLog)
    {
        messageLog = new MessageLog();
    }
    return messageLog;
}

int MessageLog::registerComponentVersion(ComponentVersion componentVersionInfo)
{
    lock();
    myComponentVersionList.push_back(componentVersionInfo);
    unlock();
    return 1;
}

int MessageLog::readVersion(std::vector <ComponentVersion> &componentVersionList)
{
    componentVersionList.push_back(versionInfo);
    return 1;
}

std::vector <ComponentVersion> MessageLog::readVersionList()
{
    lock();
    std::vector <ComponentVersion> returnVersionList=myComponentVersionList;
    unlock();
    return myComponentVersionList;
}

void MessageLog::addLog(Message addMsgLog)
{
    lock();
    allLogList.push_back(addMsgLog);
    unlock();

    saveLogFileFlag=true;

}

int MessageLog::timerSaveLogToFile()
{
//    qDebug() << "MessageLog::timerSaveLogToFile()";
    if(true==saveLogFileFlag)
    {
//        saveLogToFile();
        saveLogToXmlFile();
        saveLogFileFlag=false;
        return 1;
    }
    else
    {
        return -1;
    }
}

void MessageLog::saveLogToFile()
{

//    QVector <Message> tmpLogList;
//    lock();
//    tmpLogList=allLogList;
//    allLogList.clear();
//    unlock();

//    QFile file(logName);
//    if(!file.open(QIODevice::ReadWrite))
//    {
//        //消息预留
//        //保存日志文件失败
//    }
//    {
//        QDataStream out(&file);
//        out << (quint32)(tmpLogList.size());
//        //如果条数大于LOG_MAX_LENGTH，则删除最前面的。
//        while(LOG_MAX_LENGTH<tmpLogList.size())
//        {
//            tmpLogList.removeFirst();
//        }


//        for(int i = 0; i < tmpLogList.size();i++)
//        {
//            out << tmpLogList[i].MessageLevel
//                  <<  (qint64)tmpLogList[i].time
//                  << tmpLogList[i].robotId
//                  << QString::fromStdString(tmpLogList[i].componentClassName)
//                  << QString::fromStdString(tmpLogList[i].messageType)
//                  << tmpLogList[i].messageCode
//                  << tmpLogList[i].parameter1
//                  << tmpLogList[i].parameter2
//                  << tmpLogList[i].parameter3
//                  << tmpLogList[i].parameter4
//                  << QString::fromStdString(tmpLogList[i].MessageInformation);

////            qDebug() << "=====tmpLogList[i].robotId======"<<tmpLogList[i].robotId<<"\n\n\n";
//        }

//        file.close();
//        file.flush();//必须加，如果不加，可能关机的时候丢失文件内容。
//        qDebug() << "saveLogToFile sucess";
//    }


}

int MessageLog::saveLogToXmlFile()
{
    qDebug() << "MessageLog::saveLogToXmlFile begin,,,";
    QVector <Message> tmpLogList;
    lock();
    tmpLogList=allLogList;
    allLogList.clear();
    unlock();

    DomParser domParser;

    bool ok = domParser.openXml(xmlLogFileName, QIODevice::ReadWrite );
    if( !ok )//无法打开机器人数据文件！
    {
        domParser.closeXml();
        initial_forLogFileFialed(xmlLogFileName);
        qDebug()<<"error logFile not exist！";
        addMsg(ENUM_MSG_WARNING, "MessageLog", "MessageLog", 1300, -1 );
        return -1;
    }

    qDebug()<<"tmpLogList.size()="<<tmpLogList.size();
    for(int i=0;i<tmpLogList.size();i++)
    {
        saveOneMessageToXmlFile(&domParser,tmpLogList[i]);
    }

    domParser.closeXml(true);//保存
    qDebug() << "MessageLog::saveLogToXmlFile end";


    return 1;
}

int MessageLog::saveOneMessageToXmlFile(DomParser *domParser,Message log)
{
    ///读内部轴参数
    bool ok;
    QDomNode  mainNode = domParser->findSubNode(domParser->getRootDomElement(), "log", ok );
    if( !ok )
    {
       qDebug()<<"error no log node";
        return -1;
    }

    time_t timep;//
    struct tm* p;
    timep = log.time;  //
    p=localtime(&timep);//从tm结构体中可以取到年月日时分秒等值。
    char szTmp[50] = {0};
    strftime(szTmp,50,"%Y-%m-%d %H:%M:%S",p);    //这里输出的将是 p的时间值
    QString strTime = QString(QLatin1String(szTmp));

    domParser->addNode(mainNode,"record","");
    QDomNode  recordNode;
    QDomNodeList devNodes = mainNode.childNodes();
    recordNode=devNodes.at(devNodes.size()-1);
    domParser->addNode(recordNode,"messageLevel",log.MessageLevel);
    domParser->addNode(recordNode,"timeLong",log.time);
    domParser->addNode(recordNode,"timeString",strTime);
    domParser->addNode(recordNode,"robotId",log.robotId);
    domParser->addNode(recordNode,"componentClassName",QString::fromStdString(log.componentClassName));
    domParser->addNode(recordNode,"messageType",QString::fromStdString(log.messageType));
    domParser->addNode(recordNode,"messageCode",log.messageCode);
    domParser->addNode(recordNode,"parameter1",log.parameter1);
    domParser->addNode(recordNode,"parameter2",log.parameter2);
    domParser->addNode(recordNode,"parameter3",log.parameter3);
    domParser->addNode(recordNode,"parameter4",log.parameter4);
    domParser->addNode(recordNode,"messageInformation",QString::fromStdString(log.MessageInformation));

    return 1;

}



void MessageLog::addMessage(Message addMsgLog)
{
//    if(3905==addMsgLog.messageCode)
//    {
//        qDebug()<<"this";
//    }

    if( 1900== addMsgLog.messageCode)
    {
       isDeviceMasterInitialOkStatus=true;
    }

    addMessageTime(addMsgLog);


    lock();
    if(allMsgList.size())
    {
        for(int i = 0; i < allMsgList.size();i++)
        {
            if(addMsgLog.messageCode == allMsgList[i].messageCode)
            {
//                if(addMsgLog.robotId >= 0 )
//                {

                    if(addMsgLog.robotId == allMsgList[i].robotId)
                    {
                        allMsgList[i]=addMsgLog;//替换显示最新的
                    }
                    else
                    {
                        if(i == allMsgList.size() - 1)
                        {

                            allMsgList.push_back(addMsgLog);
                            allLogList.append(addMsgLog);
                            saveLogFileFlag=true;

                        }
                    }
//                }
//                else
//                {

//                }
                break;
            }
            else
            {
                if(i == allMsgList.size() - 1)
                {

                     allMsgList.push_back(addMsgLog);
                     allLogList.append(addMsgLog);
                     saveLogFileFlag=true;


                }
            }
        }
    }
    else
    {

        allMsgList.push_back(addMsgLog);
        allLogList.append(addMsgLog);
        saveLogFileFlag=true;

    }

    unlock();



}

int MessageLog::clearMessage(int msgIndex)
{

    //todo 调用发消息的组件，进行清除

    lock();
    if(msgIndex < allMsgList.size() && (msgIndex >= 0))
    {
        allMsgList.remove(msgIndex);
    }
    unlock();
}

int MessageLog::clearAllMessage(   )
{
    //todo 调用发消息的组件，进行清除
    this->lock();
    if(allMsgList.size())
    {
        allMsgList.clear();
    }
    this->unlock();
}

bool MessageLog::isErrorOccured()
{
    lock();

     for(int i = 0; i < allMsgList.size();i++)
     {
         if(ENUM_MSG_ERROR == allMsgList[i].MessageLevel)
         {
             unlock();
             return true;
         }
     }
     unlock();

     return false;
}

int MessageLog::getMessageInfoCode(int &errorCode, int &warnCode, int &noticeCode)
{
    errorCode=0;
    warnCode=0;
    noticeCode=0;
    lock();
     for(int i = 0; i < allMsgList.size();i++)
     {
         if(ENUM_MSG_ERROR == allMsgList[i].MessageLevel)
         {
             errorCode=allMsgList[i].messageCode;
         }
         else if(ENUM_MSG_WARNING == allMsgList[i].MessageLevel)
         {
             warnCode=allMsgList[i].messageCode;
         }
         else if(ENUM_MSG_REMIND == allMsgList[i].MessageLevel)
         {
             noticeCode=allMsgList[i].messageCode;
         }
     }
     unlock();

     return 1;
}

int MessageLog::updateControllerInfoLevel2( std::vector<struct Message> &msg_vec )
{
   if( this->trylock())
   {
        msg_vec = allMsgList.toStdVector();
        for(int i = 0; i < allMsgList.size();i++)
        {
            if(ENUM_MSG_ERROR == allMsgList[i].MessageLevel)
            {
                this->unlock();
                return allMsgList[i].robotId;
            }
        }
        this->unlock();
   }

   return 0;
}

void MessageLog::readLogFile()
{
//    QVector <Message> tmpLogList;

//    QFile file(logName);

//    quint32 tmpSize;
//    if(file.exists())
//    {
//        if(file.open(QIODevice::ReadOnly))
//        {
//            QDataStream out(&file);
//            out.setVersion(QDataStream::Qt_4_6);
//            out >> tmpSize;

//            tmpLogList.resize(tmpSize);

//            int tmpInt;
//            QString tmpStr;
//            qint64  tmpTime;

//            for(int i = 0; i < tmpLogList.size();i++)
//            {
//                out >>  tmpInt;
//                tmpLogList[i].MessageLevel = tmpInt;

//                //             std::cout << "------level------"<<tmpInt<<std::endl;

//                out >> tmpTime;
//                tmpLogList[i].time = tmpTime;

//                //              std::cout << "------tmpTime------"<<tmpTime<<std::endl;

//                out >> tmpInt;
//                tmpLogList[i].robotId = tmpInt;

//                //             std::cout << "------robotId------"<<tmpLogList[i].robotId<<std::endl;
//                out >> tmpStr;
//                tmpLogList[i].componentClassName = tmpStr.toStdString();
//                //             std::cout << "------comClass------"<<tmpStr.toStdString()<<std::endl;

//                out >> tmpStr;
//                tmpLogList[i].messageType = tmpStr.toStdString();
//                //             std::cout << "------type------"<<tmpStr.toStdString()<<std::endl;

//                out >>  tmpInt;
//                tmpLogList[i].messageCode = tmpInt;
//                //             std::cout << "------code-----"<<tmpInt<<std::endl;
//                out >>  tmpInt;
//                tmpLogList[i].parameter1 = tmpInt;
//                //             std::cout << "------p1------"<<tmpInt<<std::endl;
//                out >>  tmpInt;
//                tmpLogList[i].parameter2 = tmpInt;
//                //             std::cout << "------p2------"<<tmpInt<<std::endl;

//                out >> tmpInt;
//                tmpLogList[i].parameter3 = tmpInt;
//                //             std::cout << "------p3------"<<tmpInt<<std::endl;
//                out >> tmpInt;
//                tmpLogList[i].parameter4 = tmpInt;
//                //             std::cout << "------p4------"<<tmpInt<<std::endl;
//                out >> tmpStr;
//                tmpLogList[i].MessageInformation = tmpStr.toStdString();
//                //             std::cout << "------info------"<<tmpStr.toStdString()<<std::endl;
//            }
//        }
//    }
//    else
//    {
//        //消息预留
//        //日志文件不存在
//    }

//    lock();
//    allLogList=tmpLogList;
//    unlock();
}



void MessageLog::addMessageTime(Message &addMsg)
{
//    QDateTime current_date_time = QDateTime::currentDateTime();
//    QString current_date = current_date_time.toString("yyyy-MM-dd hh:mm:ss");
//    addMsg.time = current_date.toStdString();

    struct timespec nowTime;
    clock_gettime(CLOCK_REALTIME, &nowTime);//

    addMsg.time = nowTime.tv_sec;

}


void MessageLog::changeMessageLanguage(int language)
{
   // qDebug() << "++++currentLanguage+++++"<<currentLanguage<<"\n\n\n";

    currentLanguage = language;

    if(0 == currentLanguage)
    {
//        currentLanguage = language;
        m_pTranslator->load(":/tcrChinese.qm");
    }
    else if(1 == currentLanguage)
    {
//        currentLanguage = ENUM_LAN_CHINESE;
        m_pTranslator->load(":/tcrEnglish.qm");
    }

    QCoreApplication::installTranslator(m_pTranslator);
}


void MessageLog::startOrShutLog(int switchValue)
{
    Message message;

    message.componentClassName = "main";
    message.MessageLevel = ENUM_MSG_REMIND;
    message.messageType = "main";
    message.robotId = -1;


    switch(switchValue)
    {
        case CONTROLLER_POWER_OFF:
        {
            message.messageCode = 7000;
            message.MessageInformation = QObject::tr("关机！！").toStdString();
            break;
        }
        case CONTROLLER_POWER_ON:
        {
             message.messageCode = 7001;
             message.MessageInformation = QObject::tr("开机！！").toStdString();
            break;
        }

        addMessageTime(message);
    }

    addLog(message);
}


int MessageLog::getCurrentLanguage()
{
    return currentLanguage;
}

int MessageLog::getAllMessage(QVector <Message> &messageReturn)
{
    lock();
    messageReturn=allMsgList;
    unlock();
    return 1;
}

int MessageLog::getAllLog(QVector<Message> &logReturn)
{
    lock();
    logReturn=allLogList;
    unlock();
    return 1;
}

int MessageLog::initial_forLogFileFialed(QString xmlLogFileNameIn)
{
    QDateTime current_date_time =QDateTime::currentDateTime();
    QString newFileName=xmlLogFileNameIn+current_date_time.toString("yyyy.MM.dd-hh:mm:ss");
    QFile::rename(xmlLogFileNameIn,newFileName);

    QFile file(xmlLogFileNameIn);
    //定义文件内容字符串
    QString content= "<?xml version='1.0' encoding='UTF-8'?> <common>  <log>  </log>  </common>";
    //判断文件是否存在
    if(file.exists())
    {
    }else
    {
        //存在打开，不存在创建
        file.open(QIODevice::ReadWrite | QIODevice::Text);
        //写入内容,这里需要转码，否则报错。
        QByteArray str = content.toUtf8();
        //写入QByteArray格式字符串
        file.write(str);

    }
    //关闭文件
    file.close();
    return 1;

}


void MessageLog::addMsg(int messageLevel, string componentName, string messageType,
                           int messageCode, int robotId,
                           int parameter1, int parameter2, int parameter3, int parameter4,QString message)
{
    Message tmpMsg;
    tmpMsg.MessageLevel = messageLevel;
    tmpMsg.componentClassName = componentName;
    tmpMsg.messageType = messageType;
    tmpMsg.robotId = robotId;
    tmpMsg.messageCode = messageCode;
   // tmpMsg.time = t1.tv_sec;


    QString infomationStr;

    switch(messageCode)
    {
    case 1300:
    {
        infomationStr =  QObject::tr("机器人:")  + QString::number(robotId);
        infomationStr = infomationStr +
                QObject::tr(";旧日志文件已经损坏，已经备份并新建日志文件！");
        break;

    }



    }


    tmpMsg.MessageInformation = infomationStr.toStdString();

    // qDebug()<<"53444444444444444444444"<< tmpMsg.messageCode;
    this->addMessage(tmpMsg);
}





